/**
 * Process password by rules.
 */
package parser;

import java.util.*;

/**
 * @author robin
 *
 */
public class PasswordProcessor {
	// transform dictionary
	private Hashtable<String, String[]> transDict;
	
	// single character to represent a-z character
	private String wildcards = "&*";
	
	
	public PasswordProcessor() {
		transDict = new Hashtable<String, String[]>();
		transDict.put("1", new String[]{"i", "l"});
		transDict.put("3", new String[]{"e"});
		transDict.put("@", new String[]{"a"});
		
		// wildcards can be replaced by any char
		String[] atoz = new String['z'-'a' + 1];
		for(int i=0; i < atoz.length; i++) {
			atoz[i] = String.format("%c", 'a' + i);
		}
		
		for(int i=0; i < wildcards.length(); i++) {
			transDict.put(String.format("%c", wildcards.charAt(i)), atoz);
		}
	}
	
	
	/**
	 * find all possible shadow passwords by replacement rules.
	 * @param password input password.
	 * @return a list of all possible shadow password.
	 */
	public List<String> getShadowPasswords(String password) {
		List<String> shadowPasswords = new ArrayList<String>();
		shadowPasswords.add(password);
		
		List<String> tempList = new ArrayList<String>();
		for(Enumeration<String> keys = transDict.keys(); keys.hasMoreElements();) {
			String source = keys.nextElement();
			tempList.clear();
			for(String s : shadowPasswords) {
				if(s.contains(source)) {
					for(String sub : transDict.get(source)) {
						tempList.add(s.replace(source, sub));
					}
				}
				else {
					tempList.add(s);
				}
			}
			shadowPasswords.clear();
			shadowPasswords.addAll(tempList);
		}
		
		return shadowPasswords;
	}
	
	
	public Hashtable<String, List<ArrayDeque<Range>>> processPassword(WordSplitter splitter, String password) {
		Hashtable<String, List<ArrayDeque<Range>>> result = new Hashtable<String, List<ArrayDeque<Range>>>();
		// TODO ignore useless replacements
		for(String s : getShadowPasswords(password)) {
			result.put(s, Range.longestRanges(splitter.splitString(s)));
		}
		
		return result;
	}
}
